<%--
    Document   : DrawRoute
    Created on : Aug 11, 2009, 9:43:43 AM
    Author     : david
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">

<html style="height:100%">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />

        <link rel="stylesheet" type="text/css" href="/ext/resources/css/ext-all.css"/>
        <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
        <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false&amp;key=ABQIAAAAM8o2I5tj16bQKMUb2eWgghTzyIyaiIcyVAbEGxsZymrytUhO-RS_jxXPLwrxa4PlQ_8lIjxxYUWbKw"></script>
        <script type="text/javascript" src="/ext/adapter/ext/ext-base.js"></script>
        <script type="text/javascript" src="/ext/ext-all.js"></script>
        <title>Route Finder</title>

        <script>
            function ById(val) {
                return document.getElementById(val);
            }

            Ext.onReady(function(){
                Ext.QuickTips.init();
                var geocoder = null;
                // current location marker
                clm = getStartMarker(new GLatLng( <%=request.getParameter("startlat")%>, <%=request.getParameter("startlon")%>));
                dlm = getEndMarker(new GLatLng(<%=request.getParameter("endlat")%>, <%=request.getParameter("endlon")%>));
                var mapdiv = ById("map_canvas");
                var useragent = navigator.userAgent;
                //alert(mapdiv.style.height);



                map = new GMap2(ById("map_canvas"));
                map.enableScrollWheelZoom();
                geocoder = new GClientGeocoder();
                map.addControl(new GSmallMapControl());
                map.addControl(new GMapTypeControl());

                route_store = new Ext.data.JsonStore({
                    root: 'conns',
                    totalProperty: 'total',
                    idProperty: 'conid',
                    fields: [
                        'conid','stopid' ,'sname', 'sdesc','slatitude',
                        'slongitude', 'depid', 'dname','ddesc','dlatitude',
                        'dlongitude', 'departures',   'times'
                    ],

                    // load using script tags for cross domain, if the data in on the same domain as
                    // this page, an HttpProxy would be better
                    proxy: new Ext.data.HttpProxy({
                        url: 'getRoute.jsp'
                    })
                });

                route_store.on('load', function(astore, records, options) {
                    var first = new GDirections(null, ById("start"));
                    line = 0;
                    GEvent.addListener(first, 'load', function() {
                        map.addOverlay(first.getPolyline())
                    });
                    GEvent.addListener(first, "error", function() {
                        alert("Loading failed\n ERROR CODE: " + first.getStatus().code);
                    });

                    var rContainer = ById('route_container');
                    var wpStart = new Array(2);
                    wpStart[0] = clm.getLatLng();
                    var wpEnd = new Array(2);
                    wpEnd[0] = dlm.getLatLng();
                    shortestStartDistance = 1000;
                    shortestEndDistance = 1000;
                    rContainer.innerHTML +='<p>Depart at: ' + getTime(getDepartureTime(records[0].data));
                    var point = new GLatLng(records[0].data.slatitude, records[0].data.slongitude);
                    rContainer.innerHTML += 'Walk ' + getTimeToWalkBetween(point, clm.getLatLng()) + ' minutes to ' +  records[0].data.sname;
                    for(var i =0; i< records.length; i++) {                       
                        var tmp  = new GLatLng(records[i].data.slatitude, records[i].data.slongitude);
                        startdistance = clm.getLatLng().distanceFrom(tmp);
                        enddistance = dlm.getLatLng().distanceFrom(tmp);
                        //alert(distance +  " " + shortestdistance);
                        if (startdistance < shortestStartDistance) {
                            shortestStartDistance = startdistance;
                            wpStart[1] = new GLatLng(records[i].data.slatitude, records[i].data.slongitude);
                        }
                        if (enddistance < shortestEndDistance) {
                            shortestEndDistance = enddistance;
                            wpEnd[1] = new GLatLng(records[i].data.slatitude, records[i].data.slongitude);
                           
                        }
                    }
                    first.loadFromWaypoints(wpStart, {'getPolyline': true, "travelMode":G_TRAVEL_MODE_WALKING });

                    var next = "walk";
                    for(var i = 0; i< records.length; i++) {
                        var field = records[i];
                        next = "<p>Walk ";
                        if (field.data.times.length > 0) {
                            next = '<p>Get ' + field.data.times[0].desc;
                        }
                        var nextChange = getNextChange(i, records);
         
                        rContainer.innerHTML +=   next + ' to ' +  nextChange.dname;
                        var location = new GLatLng(field.data.slatitude, field.data.slongitude);
                        if (field.data.sname.toLowerCase().indexOf("rail") > 0) {
                            marker = createRailMarker(location, '<b>' + field.data.sname + '</b><br />' +field.data.sdesc );
                        } else {
                            marker = createBusMarker(location, '<b>' + field.data.sname + '</b><br />' +field.data.sdesc);
                        }
                        var line = new GPolyline([
                            marker.getLatLng(),
                            new GLatLng(field.data.dlatitude, field.data.dlongitude)
                        ], "#0000ff", 4);
                        map.addOverlay(line);
                        map.addOverlay(marker);
                    }

                    //Because we dont draw the last marker, we need to get it out of the last
                    //element, and draw it on the map
                    var lastConn = records[records.length-1];
                    var point = new GLatLng(lastConn.data.slatitude, lastConn.data.slongitude);
                    rContainer.innerHTML += '<p>Walk ' + getTimeToWalkBetween(point, dlm.getLatLng()) + ' minutes to destination';
                    rContainer.innerHTML +='<p>Arrive at: ' + getTime(getArrivalTime(lastConn.data));
                    
                    var m = null;
                    var l = new GLatLng(lastConn.data.dlatitude, lastConn.data.dlongitude);
                    if (lastConn.data.dname.toLowerCase().indexOf("rail") > 0) {
                        m = createRailMarker(l, '<b>' + lastConn.data.dname + '</b><br />' +lastConn.data.ddesc);
                    } else {
                        m = createBusMarker(l, '<b>' + lastConn.data.dname + '</b><br />' +lastConn.data.ddesc);
                    }
                    map.addOverlay(m);
                    

                    wpEnd[1] = m.getLatLng();
                    var last = new GDirections(null, ById("end"));
                    GEvent.addListener(last, 'load', function() {
                        map.addOverlay(last.getPolyline())
                    });
                    GEvent.addListener(last, "error", function() {
                        alert("Loading failed\n ERROR CODE: " + last.getStatus().code);
                    });
                    last.loadFromWaypoints( wpEnd , {'getPolyline': true, "travelMode":G_TRAVEL_MODE_WALKING } );
                    
                    ById("end").style.visibility="hidden";
                    ById("start").style.visibility="hidden";
                    
                });


                // Creates a marker whose info window displays the letter corresponding
                // to the given index.
                function createBlueMarker(point, title) {
                    var gi = new GIcon(G_DEFAULT_ICON);
                    gi.image = "http://maps.google.com/mapfiles/ms/micons/lightblue.png";
                    gi.shadow ="http://www.google.com/mapfiles/shadow50.png";
                    gi.iconSize = new GSize(18,18);
                    gi.shadowSize = new GSize(18,18);
                    return createMarker(point, title, gi);
                }
                // Creates a marker whose info window displays the letter corresponding
                // to the given index.
                function createRailMarker(point, title) {
                    var gi = new GIcon(G_DEFAULT_ICON);
                    gi.image = "http://maps.google.com/mapfiles/ms/micons/rail.png";
                    gi.shadow ="http://maps.google.com/mapfiles/ms/micons/rail.shadow.png";
                    gi.iconSize = new GSize(24,24);
                    gi.shadowSize = new GSize(24,24);
                    return createMarker(point, title, gi);
                }

                function createBusMarker(point, title) {
                    var gi = new GIcon(G_DEFAULT_ICON);
                    gi.image = "http://maps.google.com/mapfiles/ms/micons/bus.png";
                    gi.shadow ="http://maps.google.com/mapfiles/ms/micons/bus.shadow.png";
                    gi.iconSize = new GSize(24,24);
                    gi.shadowSize = new GSize(24,24);
                    return createMarker(point, title, gi);
                }

                function createMarker(point, title, icon) {
                    var marker = new GMarker(point,{icon: icon});
                    GEvent.addListener(marker, "click", function() {
                        marker.openInfoWindowHtml(title);
                    });
                    return marker;
                }

                function getStartMarker(point) {
                    var gi = new GIcon(G_DEFAULT_ICON);
                    gi.image = "http://www.google.com/mapfiles/dd-start.png";
                    gi.shadow ="http://www.google.com/mapfiles/shadow50.png";
                    return createDraggableMarker(point, gi, false, true);
                }

                function getEndMarker(point) {
                    var gi = new GIcon(G_DEFAULT_ICON);
                    gi.image = "http://www.google.com/mapfiles/dd-end.png";
                    gi.shadow ="http://www.google.com/mapfiles/shadow50.png";
                    return createDraggableMarker(point, gi, true, false);
                }
                // Creates a marker whose info window displays the letter corresponding
                // to the given index.
                function createDraggableMarker(point, icon, start, end) {

                    var marker = new GMarker(point, { icon:icon, draggable: false});


                    GEvent.addListener(marker, "dragstart", function() {
                        map.closeInfoWindow();
                    });

                    GEvent.addListener(marker, "dragend", function() {
                        //marker.openInfoWindowHtml("New Start Point");

                        loadStops(start, end);
                    });
                    return marker;

                }

                //***************************************************************************************
                // Function:    getNextChange
                // param:       index int
                // return:      connection object
                //***************************************************************************************
                function getNextChange(index, records) {
                    //Now we check the description of the first departure time, if they are the same, we do not change,
                    // otherwise, we return a stop if the time description is different
                    for (var i = index +1; i < records.length ; i++  ) {
                        //Get the connection object
                        var conn = records[i].data;
                        // if there are no times, that means we walk the current time
                        if  (conn.times.length == 0 || records[index].data.times.length == 0 ) {
                            return conn;
                        }
                        if (conn.times[0].desc != records[index].data.times[0].desc){
                            return conn;
                        }
                    }
                    //here we have not found a change, so this route just involves one train/bus
                    return records[records.length-1].data;

                }

                //***************************************************************************************
                // Function:    getTime
                // param:       value (Date) the date object you want to get the time from
                // return:      the time in HH:MM format
                //***************************************************************************************
                function getTime(value) {
                    value = new Date(value);
                    var minutes = value.getMinutes();
                    if (minutes < 10) minutes ="0" + minutes;
                    return value.getHours() + ":" + minutes;
                }

                //***************************************************************************************
                // Function:    getDepartureTime
                // param:       conn (the connection object from the data store)
                // return:      The departure time in the format of hh:mm
                //***************************************************************************************
                function getDepartureTime(conn) {
                    if (conn.times.length == 0) {
                        alert('TODO! Investigate this');
                        return null;
                    }
                    return getFirstTimeAt(conn.slatitude, conn.slongitude, clm, true, conn.times[0].time);
                }

                //***************************************************************************************
                // Function:    getArrivalTime
                // param:       conn  (the connection object from the data store)
                // return:      The arrival time in the format of hh:mm
                //***************************************************************************************
                function getArrivalTime(conn) {
                    if (conn.times.length == 0) {
                        alert('TODO! Investigate this too!');
                        return null;
                    }
                    return getFirstTimeAt(conn.dlatitude, conn.dlongitude, dlm, false, conn.times[0].time);
                }

                //***************************************************************************************
                // Function:    getFirstTimeAt
                //
                // param:       lat (float) the latitude of the point to compare calculate the time
                // param:       lon (float) The longitude of the point used to  calculate the time
                // param:       aMarker (Gmaker) the marker used to calculate the time to travel to
                // param:       departure (Bool) do you want to calculate the deaprture time?
                //              otherwise, it calculates the arrival time
                // param:       time the current time
                // return:      The time to depart or arrive
                //***************************************************************************************
                function getFirstTimeAt(lat, lon, aMarker, departure, time) {
                    var conn = new GLatLng(lat, lon);
                    var Time = new Date(time);
                    var minutesToWalk = getTimeToWalkBetween(aMarker.getLatLng(), conn);
                    //If its a departure we want to add walking time
                    if(departure) {
                        Time.setMinutes(Time.getMinutes() -  minutesToWalk);
                    } else {
                        Time.setMinutes(Time.getMinutes() +  minutesToWalk);
                    }
                    return Time;
                }
                //***************************************************************************************
                // Function:getTimeToWalkBetween
                // param:   point1 (GMarker)
                // param:   point2 (GMarker)
                // return:  the time taken to walk from one point to anotehr at a very leasurely pace
                //***************************************************************************************
                function getTimeToWalkBetween(point1, point2){
                    //distance in meters
                    var distance = point1.distanceFrom(point2);
                    var minutes = distance * 0.02;
                    return Math.ceil(minutes);
                }

                function getLocation(){
                    //alert(1);
                    if(navigator.geolocation) {
                        navigator.geolocation.getCurrentPosition(function(p){
                            clm = getStartMarker(new GLatLng( p.coords.latitude,  p.coords.longitude));

                        });
                    }

                }

                function loadStops(start, end) {
                    map.clearOverlays();

                    route_store.load({params:{
                            from: '<%=request.getParameter("from")%>',
                            to: '<%=request.getParameter("to")%>',
                            time: '8:45',
                            range: 40
                        }
                    });
       
                    drawStartEnd(start == end);

                }
                function drawStartEnd(centered) {
                    if (clm) map.addOverlay(clm);
                    if (dlm) map.addOverlay(dlm);
                    if (centered) {
                        var cen = new GLatLng(
                        (clm.getLatLng().lat() + dlm.getLatLng().lat()) / 2,
                        (clm.getLatLng().lng() + dlm.getLatLng().lng()) / 2);
                        map.setCenter(cen, 13);
                    }
                }



                function ById(val) {
                    return document.getElementById(val);
                }

                loadStops(true,true);
            });
        </script>
    </head>
    <body style="height:100%; margin:0;">
        <div id="map_canvas" style="width:100%; height:100%"></div>
        <div>
            <form>
                <div id="start" style="position:absolute; top:0; left:0;"></div>
                <div id="end" style="position:absolute; top:0; left:0;"></div>
                <input type="hidden" id="destination" name="destination">
            </form>
            <div id="route_container">


            </div>
        </div>
    </body>

</html>
